/**
 * 
 */
package org.melord.cap;

import java.util.ArrayList;

import jpcap.NetworkInterface;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
import org.melord.cap.lic.Validator;

/**
 * @author melord
 * 
 */
public class MonitorService {
	private Capture capture = new Capture();
	private HttpMonitor monitor = new HttpMonitor();
	private Shell shell;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MonitorService service = new MonitorService();
		service.init();
	}

	public void init() {

		int code = new Validator().validate();
		System.out.println("code:" + code); //$NON-NLS-1$
		if (code < 16) {
			dialog(
					Messages.getString("MonitorService.1"), Messages.getString("MonitorService.2")); //$NON-NLS-1$ //$NON-NLS-2$
			System.exit(code);
		} else if (code > 0x20) {
			dialog(
					Messages.getString("MonitorService.3"), Messages.getString("MonitorService.4")); //$NON-NLS-1$ //$NON-NLS-2$
			System.exit(code);
		} else if (code != 0x11 && code != 0x12) {
			dialog(
					Messages.getString("MonitorService.5"), Messages.getString("MonitorService.6")); //$NON-NLS-1$ //$NON-NLS-2$
			System.exit(code);
		}

		Display display = new Display();
		shell = new Shell(display);
		final Tray tray = display.getSystemTray();
		createTray(shell, tray);
		try {
			monitor.loadHosts();
		} catch (Exception e) {
			dialog(Messages.getString("MonitorService.7"), e.toString()); //$NON-NLS-1$
			e.printStackTrace();
			System.exit(0x01);
		}
		capture.setReceiver(monitor);
		monitor.setCallback(callback);

		final NetworkInterface[] devices = capture.getDevices();
		if (devices == null || devices.length == 0){
			System.out.println("can't get network devices");
		}
		NetworkInterface deviceToMonitor = null;
		for (NetworkInterface device : devices) {
			System.out.println(String.format(
					"find device :%s desc=%s, dlname=%s, dldesc=%s",
					device.name, device.description, device.datalink_name,
					device.datalink_description));
			if (Cfg.getInstance().getDeviceName().equals(
					device.description.trim())) {
				deviceToMonitor = device;
				System.out.println("use device " + device.description);
				break;
			}
		}
		if (deviceToMonitor == null && devices.length > 0) {
			System.out
					.println("can't init device from config, use the first device");
			deviceToMonitor = devices[0];
		}
		if (deviceToMonitor != null) {
			capture.setDevice(deviceToMonitor);
		}

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

	private void createTray(final Shell shell, Tray tray) {
		if (tray != null) {
			final TrayItem item = new TrayItem(tray, SWT.NONE);
			final Image image = new Image(shell.getDisplay(),
					MonitorService.class.getResourceAsStream("tray.png")); //$NON-NLS-1$
			item.setImage(image);
			final Menu menu = new Menu(shell, SWT.POP_UP);
			MenuItem miOption = new MenuItem(menu, SWT.PUSH);
			miOption.setText("选项");
			miOption.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					OptionDialog dialog = new OptionDialog(shell,
							SWT.DIALOG_TRIM);
					dialog.setCapture(capture);
					int code = dialog.open();

				}
			});

			MenuItem mi = new MenuItem(menu, SWT.PUSH);
			mi.setText(Messages.getString("MonitorService.menu.exit")); //$NON-NLS-1$
			mi.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					image.dispose();
					item.dispose();
					capture.stop();
					shell.dispose();
					System.exit(0);
				}
			});

			item.addListener(SWT.MenuDetect, new Listener() {
				public void handleEvent(Event event) {
					menu.setVisible(true);
				}
			});
		}
	}

	private void dialog(String title, String msg) {
		try {
			Display display = Display.getDefault();
			Shell shell = new Shell(display);

			MessageBox box = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
			box.setMessage(msg);
			box.setText(title);
			box.open();

			shell.dispose();
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Popup.Callback popupCallback = new Popup.Callback() {

		@Override
		public void onDismiss(Host host) {
			removeHost(host);
		}

	};
	private HttpMonitor.Callback callback = new HttpMonitor.Callback() {

		@Override
		public void receive(final Host host) {
			// System.out.println("received!");

			if (!urls.contains(host.getHttpRequest().getReferer())) {
				System.out.println(host);
				urls.add(host.getHttpRequest().getReferer());

				Thread thread = new Thread() {
					public void run() {
						PopupDialog popup = new PopupDialog(shell, host, System
								.currentTimeMillis());
						popup.setPopupListener(new PopupDialog.PopupListener() {

							@Override
							public void onClose(Host host) {
								System.out.println("remove:" + host);
								urls.remove(host.getHttpRequest().getReferer());
							}
						});
						popup.open();
					}
				};
				shell.getDisplay().asyncExec(thread);
			}
		}
	};

	ArrayList<Host> hosts = new ArrayList<Host>();

	public void removeHost(Host host) {
		int idx = -1;
		for (int i = 0; i < hosts.size(); i++) {
			if (host.equals(hosts.get(i))) {
				idx = i;
				break;
			}
		}
		if (idx >= 0) {
			hosts.remove(idx);
		}
	}

	ArrayList<String> urls = new ArrayList<String>();

	public void removeUrl(String url) {
		int idx = -1;
		for (int i = 0; i < urls.size(); i++) {
			if (url.equals(urls.get(i))) {
				idx = i;
				break;
			}
		}
		if (idx >= 0) {
			urls.remove(idx);
		}
	}
}
